From c8cf49e882fd2e0aa7450e25c7b5b785dc97c725 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Fri, 24 Jun 2005 08:16:13 +0000 Subject: [PATCH] bitkeeper revision 1.1748 (42bbc14djIjScNrLp20eDhlxUjQl4g) xenstored_transaction.c, xenstored_core.h, xenstored_core.c, TODO: Update TODO list Wrap opendir in talloc so it gets cleaned up on OOM. Remove last call to system by open-coding "cp -al" to create transaction. Signed-off-by: Rusty Russell Signed-off-by: Christian Limpach --- tools/xenstore/TODO | 4 +- tools/xenstore/xenstored_core.c | 35 +++++++++-- tools/xenstore/xenstored_core.h | 11 ++++ tools/xenstore/xenstored_transaction.c | 84 +++++++++++++++++++------- 4 files changed, 106 insertions(+), 28 deletions(-) diff --git a/tools/xenstore/TODO b/tools/xenstore/TODO index 9e22afe536..8e4185b211 100644 --- a/tools/xenstore/TODO +++ b/tools/xenstore/TODO @@ -4,4 +4,6 @@ reader to fill in the blanks. - Remove calls to system() from daemon - Timeout failed watch responses -- Timeout blocking transactions +- Dynamic nodes +- Persistant storage of introductions, watches and transactions, so daemon can restart +- Remove assumption that rename doesn't fail diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 9f7ff2e1ce..b6db6995c4 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -246,7 +246,7 @@ static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock, } /* Read everything from a talloc_open'ed fd. */ -static void *read_all(int *fd, unsigned int *size) +void *read_all(int *fd, unsigned int *size) { unsigned int max = 4; int ret; @@ -271,7 +271,7 @@ static int destroy_fd(void *_fd) } /* Return a pointer to an fd, self-closing and attached to this pathname. */ -static int *talloc_open(const char *pathname, int flags, int mode) +int *talloc_open(const char *pathname, int flags, int mode) { int *fd; @@ -534,6 +534,30 @@ static char *tempfile(const char *path, void *contents, unsigned int len) return tmppath; } +static int destroy_opendir(void *_dir) +{ + DIR **dir = _dir; + closedir(*dir); + return 0; +} + +/* Return a pointer to a DIR*, self-closing and attached to this pathname. */ +DIR **talloc_opendir(const char *pathname) +{ + DIR **dir; + + dir = talloc(pathname, DIR *); + *dir = opendir(pathname); + if (!*dir) { + int saved_errno = errno; + talloc_free(dir); + errno = saved_errno; + return NULL; + } + talloc_set_destructor(dir, destroy_opendir); + return dir; +} + /* We assume rename() doesn't fail on moves in same dir. */ static void commit_tempfile(const char *path) { @@ -677,7 +701,7 @@ static bool send_directory(struct connection *conn, const char *node) { char *path, *reply = talloc_strdup(node, ""); unsigned int reply_len = 0; - DIR *dir; + DIR **dir; struct dirent *dirent; node = canonicalize(conn, node); @@ -685,11 +709,11 @@ static bool send_directory(struct connection *conn, const char *node) return send_error(conn, errno); path = node_dir(conn->transaction, node); - dir = opendir(path); + dir = talloc_opendir(path); if (!dir) return send_error(conn, errno); - while ((dirent = readdir(dir)) != NULL) { + while ((dirent = readdir(*dir)) != NULL) { int len = strlen(dirent->d_name) + 1; if (!valid_chars(dirent->d_name)) @@ -699,7 +723,6 @@ static bool send_directory(struct connection *conn, const char *node) strcpy(reply + reply_len, dirent->d_name); reply_len += len; } - closedir(dir); return send_reply(conn, XS_DIRECTORY, reply, reply_len); } diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h index a82ae8b22e..4ad207537b 100644 --- a/tools/xenstore/xenstored_core.h +++ b/tools/xenstore/xenstored_core.h @@ -20,6 +20,8 @@ #ifndef _XENSTORED_CORE_H #define _XENSTORED_CORE_H +#include +#include #include #include #include @@ -129,7 +131,16 @@ void handle_output(struct connection *conn); /* Is this a valid node name? */ bool is_valid_nodename(const char *node); +/* Return a pointer to an open dir, self-closig and attached to pathname. */ +DIR **talloc_opendir(const char *pathname); + +/* Return a pointer to an fd, self-closing and attached to this pathname. */ +int *talloc_open(const char *pathname, int flags, int mode); + /* Convenient talloc-style destructor for paths. */ int destroy_path(void *path); +/* Read entire contents of a talloced fd. */ +void *read_all(int *fd, unsigned int *size); + #endif /* _XENSTORED_CORE_H */ diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c index dd70579109..96d45a6b9c 100644 --- a/tools/xenstore/xenstored_transaction.c +++ b/tools/xenstore/xenstored_transaction.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "talloc.h" #include "list.h" #include "xenstored_transaction.h" @@ -137,7 +138,7 @@ void add_change_node(struct transaction *trans, const char *node) char *node_dir_inside_transaction(struct transaction *trans, const char *node) { - return talloc_asprintf(node, "%s%s", trans->divert, + return talloc_asprintf(node, "%s/%s", trans->divert, node + strlen(trans->node)); } @@ -170,33 +171,74 @@ void check_transaction_timeout(void) } } -/* FIXME: Eliminate all uses of this */ -static bool do_command(const char *cmd) +static int destroy_transaction(void *_transaction) +{ + struct transaction *trans = _transaction; + + list_del(&trans->list); + return destroy_path(trans->divert); +} + +static bool copy_file(const char *src, const char *dst) { - int ret; + int *infd, *outfd; + void *data; + unsigned int size; - ret = system(cmd); - if (ret == -1) + infd = talloc_open(src, O_RDONLY, 0); + if (!infd) return false; - if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) { - errno = EIO; + outfd = talloc_open(dst, O_WRONLY|O_CREAT|O_EXCL, 0640); + if (!outfd) return false; - } - return true; + data = read_all(infd, &size); + if (!data) + return false; + return xs_write_all(*outfd, data, size); } -static int destroy_transaction(void *_transaction) +static bool copy_dir(const char *src, const char *dst) { - struct transaction *trans = _transaction; + DIR **dir; + struct dirent *dirent; - list_del(&trans->list); - return destroy_path(trans->divert); + if (mkdir(dst, 0750) != 0) + return false; + + dir = talloc_opendir(src); + if (!dir) + return false; + + while ((dirent = readdir(*dir)) != NULL) { + struct stat st; + char *newsrc, *newdst; + + if (streq(dirent->d_name, ".") || streq(dirent->d_name, "..")) + continue; + + newsrc = talloc_asprintf(src, "%s/%s", src, dirent->d_name); + newdst = talloc_asprintf(src, "%s/%s", dst, dirent->d_name); + if (stat(newsrc, &st) != 0) + return false; + + if (S_ISDIR(st.st_mode)) { + if (!copy_dir(newsrc, newdst)) + return false; + } else { + if (!copy_file(newsrc, newdst)) + return false; + } + /* Free now so we don't run out of file descriptors */ + talloc_free(newsrc); + talloc_free(newdst); + } + return true; } bool do_transaction_start(struct connection *conn, const char *node) { struct transaction *transaction; - char *dir, *cmd; + char *dir; if (conn->transaction) return send_error(conn, EBUSY); @@ -213,14 +255,9 @@ bool do_transaction_start(struct connection *conn, const char *node) /* Attach transaction to node for autofree until it's complete */ transaction = talloc(node, struct transaction); transaction->node = talloc_strdup(transaction, node); - transaction->divert = talloc_asprintf(transaction, "%s/%p/", + transaction->divert = talloc_asprintf(transaction, "%s/%p", xs_daemon_transactions(), transaction); - cmd = talloc_asprintf(node, "cp -a %s %s", dir, transaction->divert); - if (!do_command(cmd)) - corrupt(conn, "Creating transaction %s", transaction->divert); - - talloc_steal(conn, transaction); INIT_LIST_HEAD(&transaction->changes); transaction->conn = conn; timerclear(&transaction->timeout); @@ -228,6 +265,11 @@ bool do_transaction_start(struct connection *conn, const char *node) list_add_tail(&transaction->list, &transactions); conn->transaction = transaction; talloc_set_destructor(transaction, destroy_transaction); + + if (!copy_dir(dir, transaction->divert)) + return send_error(conn, errno); + + talloc_steal(conn, transaction); return send_ack(transaction->conn, XS_TRANSACTION_START); } -- 2.30.2